package com.mall.framework.shiro.realm;

import com.mall.common.exception.user.*;
import com.mall.framework.shiro.service.SysLoginService;
import com.mall.framework.util.ShiroUtils;
import com.mall.system.domain.entity.SysUser;
import com.mall.system.service.SysMenuService;
import com.mall.system.service.SysRoleService;
import java.util.HashSet;
import java.util.Set;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 自定义Realm 处理登录 权限
 * Created by zhonglin on 2020/4/8.
 */
public class UserRealm
    extends AuthorizingRealm {

  private static final Logger log = LoggerFactory.getLogger(UserRealm.class);

  @Autowired
  private SysMenuService menuService;

  @Autowired
  private SysRoleService roleService;

  @Autowired
  private SysLoginService loginService;

  /**
   * 授权
   */
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {

    SysUser user = ShiroUtils.getSysUser();
    // 角色列表
    Set<String> roles = new HashSet<String>();
    // 功能列表
    Set<String>             menus = new HashSet<String>();
    SimpleAuthorizationInfo info  = new SimpleAuthorizationInfo();
    // 管理员拥有所有权限
    if (user.isAdmin()) {
      info.addRole("admin");
      info.addStringPermission("*:*:*");
    } else {
      roles = roleService.selectRoleKeys(user.getUserId());
      menus = menuService.selectPermsByUserId(user.getUserId());
      // 角色加入AuthorizationInfo认证对象
      info.setRoles(roles);
      // 权限加入AuthorizationInfo认证对象
      info.setStringPermissions(menus);
    }
    return info;
  }

  /**
   * 登录认证
   */
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
      throws AuthenticationException {

    UsernamePasswordToken upToken  = (UsernamePasswordToken) token;
    String                username = upToken.getUsername();
    String                password = "";
    if (upToken.getPassword() != null) {
      password = new String(upToken.getPassword());
    }

    SysUser user = null;
    try {
      user = loginService.login(username, password);
    } catch (CaptchaException e) {
      throw new AuthenticationException(e.getMessage(), e);
    } catch (UserNotExistsException e) {
      throw new UnknownAccountException(e.getMessage(), e);
    } catch (UserPasswordNotMatchException e) {
      throw new IncorrectCredentialsException(e.getMessage(), e);
    } catch (UserPasswordRetryLimitExceedException e) {
      throw new ExcessiveAttemptsException(e.getMessage(), e);
    } catch (UserBlockedException e) {
      throw new LockedAccountException(e.getMessage(), e);
    } catch (RoleBlockedException e) {
      throw new LockedAccountException(e.getMessage(), e);
    } catch (Exception e) {
      log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage());
      throw new AuthenticationException(e.getMessage(), e);
    }
    SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
    return info;
  }

  /**
   * 清理缓存权限
   */
  public void clearCachedAuthorizationInfo() {

    this.clearCachedAuthorizationInfo(SecurityUtils.getSubject()
                                                   .getPrincipals());
  }

}
